package com.sky.aspect;

import com.sky.anno.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperatorType;
import com.sky.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @Description 时间字段自动填充
 * @Author zhuzi
 * @Date 2023/09/25
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    // 配置切点表达式
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.anno.AutoFill)")
    public void autoFillPC() {
    }

    // 前置增强
    @Before("autoFillPC()")
    public void autoFillBefore(JoinPoint jp) throws Exception {
        // 准备插入数据
        LocalDateTime ldt = LocalDateTime.now();
        Long UserId = BaseContext.getCurrentId();

        // 获得方法参数
        Object[] args = jp.getArgs();
        if (args == null || args.length == 0) {
            throw new BaseException("八戒 你又瞎打注解了~");
        }

        // 反射获得方法（update）
        Class<?> clazz = args[0].getClass();
        Method setUpdateTime = clazz.getDeclaredMethod("setUpdateTime", LocalDateTime.class);
        setUpdateTime.setAccessible(true);
        setUpdateTime.invoke(args[0], ldt);
        Method setUpdateUser = clazz.getDeclaredMethod("setUpdateUser", Long.class);
        setUpdateUser.setAccessible(true);
        setUpdateUser.invoke(args[0], UserId);

        // 获得方法签名
        MethodSignature signature = (MethodSignature) jp.getSignature();

        // 获得注解对象
        AutoFill anno = signature.getMethod().getAnnotation(AutoFill.class);

        // 判断操作类型
        if (anno.value().equals(OperatorType.INSERT)) {
            // 反射获得方法（insert）
            Method setCreateTime = clazz.getDeclaredMethod("setCreateTime", LocalDateTime.class);
            setCreateTime.setAccessible(true);
            setCreateTime.invoke(args[0], ldt);
            Method setCreateUser = clazz.getDeclaredMethod("setCreateUser", Long.class);
            setCreateUser.setAccessible(true);
            setCreateUser.invoke(args[0], UserId);
        }

        log.info("自动填充完毕");
    }

}
